# # 切片
# books = ['中医理论基础','中医诊断学','中药学','方剂学','中医内科学','中医妇科学','中医儿科学']
# print(books)
# print(books[0:4]) # 取出前4个元素，注意索引表示的区间是前闭后开
# print(books[:4]) # 取出前4个
# print(books[2:5]) # 取出2~5个
# print(books[-3:]) # 取出最后3个，注意-1是最后一个
# print(books[-4:-2]) # 取出倒数2~4个

# L = list(range(100))
# # print(L)
# print(L[:10])
# print(L[10:20])
# print(L[-10:])
# print(L[:10:2]) # 取出前10个，每2个切一个
# print(L[::5]) # 所有元素每5个切一个
# # print(L[:]) # 复制出一份list
# T = (0,1,2,3,4,5)
# print(T[1:]) # tuple也可以进行切片，但结果仍然是tuple
# print(T[:-2])
# S = '关中刀客在青岛'
# print(S[:4]) # 字符串切片后结果是字符串
# print(S[::2])

# 练习题，使用切片实现trim()函数
# def trim(s):
    # length = len(s)

    # front = 0
    # while(front<length):
        # if s[front:front+1] != ' ':
            # break
        # front += 1

    # back = length-1
    # while(back>=0):
        # if s[back:back+1] != ' ':
            # break
        # back -= 1
    # print(s,front,back)
    # return s[front:back+1]

# 其他优雅写法
# def trim(s):
    # while s[:1] == ' ':
        # s = s[1:]
    # while s[-1:] == ' ':
        # s = s[:-1]
    # return s
    
# def trim(s):
    # if s[0:1]==' ':
        # return trim(s[1:])
    # elif s[-1:]==' ':
        # return trim(s[0:-1])
    # else :
        # return s

# print(trim('hello  ') == 'hello')
# print(trim('  hello') == 'hello')
# print(trim('  hello  ') == 'hello')
# print(trim('  hello  world  ') == 'hello  world')
# print(trim('') == '')
# print(trim('    ') == '')

# 迭代
# books = ['窗边的小豆豆','夏洛的网','团圆','宫西达也的恐龙']
# print('\n~~阿洛的书:')
# for book in books:
    # print('《%s》' % book)
# cars = ('婴儿大车','婴儿篷车','牛牛车','万向车','黄塑料木马','电动摩托车','高级三轮车','简易三轮车')
# print('\n~~阿洛的玩具车:')
# for car in cars:
    # print('《%s》' % car)
# # 遍历dict
# baby = {'name':'json','sex':'boy','age':'3','city':'qingdao'}
# # 默认遍历dict的key
# for key in baby:
    # print(key)
# # 遍历dict的value
# for v in baby.values():
    # print(v)
# # 遍历dict的键值对
# for k,v in baby.items():
    # print(k,v)
# # 遍历字符串
# for s in 'daoke':
    # print(s)

# from collections.abc import Iterable

# print(isinstance('daoke',Iterable))
# print(isinstance([1,2,3],Iterable))
# print(isinstance((1,),Iterable))
# print(isinstance(123,Iterable))

# # list实现索引与内容的遍历
# books = ['窗边的小豆豆','夏洛的网','团圆','宫西达也的恐龙']
# for index,book in enumerate(books):
    # print('%s：《%s》' % (index+1,book))
    
# #练习题 请使用迭代查找一个list中最小和最大值，并返回一个tuple
# def findMinAndMax(L):
    # if not len(L):
        # return (None,None)
    # min = max  = L[0]
    # for n in L:
        # if n < min:
            # min = n
        # if n > max:
            # max = n
    # print(min, max)
    # return (min, max)
    
# print(findMinAndMax([]))
# findMinAndMax([7])
# findMinAndMax([7, 1])
# findMinAndMax([7, 1, 3, 9, 5])

# 列表生成式
# 一种python内置的list生成式
# 生成1~10的列表
# L = list(range(1,11))
# print(L)
# # 生成上述每个元素平方的列表
# print([x * x for x in L])
# # 两层循环
# print([m+n for m in 'abc' for n in 'xyz'])
# # 列出当前目录下所有文件和目录名
# import os
# print([d for d in os.listdir('.')])
# # 遍历dict的键值对
# baby = {'name':'madan','sex':'boy','age':'6','city':'baoji'}
# madanKV = [k+'='+v for k,v in baby.items() ]
# print(madanKV)
# # 将字符串中的大写全部改为小写
# S = ['Hello World','DAOKE','Madan','hadi']
# lowerS = [s.lower() for s in S]
# print(lowerS)

# # 加上if条件生成偶数,if在for后面不能写else
# even = [x for x in L if x%2==0]
# print(even)
# # if写在for前面，表示生成后对结果再进行修改输出，必须写上else
# even = [x if x%2==0 else -x for x in L]
# print(even)

# 生成器
# 将列表生成式两头的方括号改为圆括号，就会得到一个生成器
# g = (x*x for x in range(6))
#直接打印输出个生成器类型：<generator object <genexpr> at 0x000001D599E69570>
# print(g)
# 打印输出，通过next()计算出下一个值
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# 通过for循环输出,不用担心遍历越界，这才是正常使用的方法
# for x in g:
    # print(x)
# 斐波那契数列，用函数写成
# def fib(max):
    # n,a,b = 0,0,1
    # L = []
    # while n < max:
        # # 下面的赋值相当于如下三句
            # # t = (a,a+b)
            # # a = t[0]
            # # b = t[1]
        # L.append(b)
        # a,b = b,a+b
        # n += 1
    # return L

# print(fib(20))

# 将上面的函数改为generator，每调用一次才生成当前的数
# def fib(max):
    # n,a,b = 0,0,1
    # while n < max:
        # # 下面的赋值相当于如下三句
            # # t = (a,a+b)
            # # a = t[0]
            # # b = t[1]
        # yield b
        # a,b = b,a+b
        # n += 1
    # return 'done'

# 定义一个打印函数
# def odd(max):
    # g = fib(max)
    # L = []
    # for x in g:
        # L.append(x)
    # return L
    
# print(odd(20))

# 解析：函数中如果包含关键字yield，那么个函数就是一个generator。
#       generator每次被next()调用时执行，遇到yield就返回后面的表达式，
#       再次执行时从上次返回的yield语句处继续执行
# 注意：在使用for in 循环执行generator时，不能直接拿到generator最后的返回值，即return后面的内容。
#       如果想拿到，就要捕获StopIteration错误，值包含在StopIteration的value中。
#       下面通过while和next来实现，用try…except…捕获错误，注意except里面要用break中断，否则会死循环
# def odd_get_return(max):
    # g = fib(max)
    # while True:
        # try:
            # print(next(g))
        # except StopIteration as e:
            # print('捕获到StopIteration的value值是：', e.value)
            # break
# odd_get_return(20)
# def triangles():
    # yield [1]
    # L = [1,1]
    # yield L

    # while True:
        # L_new = [1]
        # for idx,v in enumerate(L):
            # if idx==len(L)-1:
                # continue
            # L_new.append(v+L[idx+1])
        # L_new.append(1)
        # L = L_new
        # yield L
# # 其他优雅写法
# def triangles():
    # pre = [1]   
    # n = 2
    # while True:
        # yield pre
        # pre = [x + pre[i-1] if i-1 >=0 else x for i,x in enumerate(pre)]
        # pre.append(1)
       
# # 测试        
# n = 0
# results = []
# for t in triangles():
    # results.append(t)
    # n = n + 1
    # if n == 10:
        # break

# for t in results:
    # print(t)

# 迭代器

# # 直接可作用于for循环的数据类型可分为两类：
# # 一类是集合数据类型list、tuple、dict、str、set等， 
# # 另一类是generator，包括生成器和带yield的函数
# # 可用于for循环迭代的对象称为可迭代对象：Iterable
# # 可以用isinstance来判断一个对象是否Iterable对象：
# from collections.abc import Iterable
# print(isinstance([],Iterable))# True
# print(isinstance({},Iterable))# True
# print(isinstance('daoke',Iterable))# True
# print(isinstance((x for x in range(10)),Iterable))# True
# print(isinstance(818,Iterable)) # False
 
# #如上所述第二类可迭代对象，称为迭代器，可被next()调用不断返回下一个值
# # 可以使用isinstance判断一个对象是否迭代器
# from collections.abc import Iterator
# print(isinstance([],Iterator)) # False
# print(isinstance({},Iterator)) # False
# print(isinstance('daoke',Iterator)) # False
# print(isinstance((x for x in range(10)),Iterator))# True

# 可以使用iter()函数把list、dict、str等类型转成迭代器
from collections.abc import Iterator
print(isinstance(iter([]),Iterator)) # True
print(isinstance(iter({}),Iterator)) # True
print(isinstance(iter('daoke'),Iterator)) # True

# 总结
# Iterator对象表示一个数据流，是一个惰性的有序序列，只能通过next()按需计算下一个数值，但不能提前知道整个序列的长度。
# Iterator可表示无限大的数据流，如全体自然数，而list只能表示有限的数据集合
# 对Iterator进行for循环时，本质上是调用next()方法实现的
